﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Viettel.VOFFICE.DAO.DAL.Paging;
using Viettel.VOFFICE.DAO.Models;

namespace Viettel.VOFFICE.DAO.DAL.Repository
{
    /// <summary>
    /// Lưu thông tin cơ bản nhất về mộ luồng xử lý công văn
    /// dùng để chọn luồng xử lý cho 1 công văn đến
    /// </summary>
    public class FlowRepository : IRepository<Flow>
    {
        private VOFFICEContext context;
        public FlowRepository(VOFFICEContext context)
        {
            if (context == null)
            {
                throw new Exception("Context must be init");
            }
            this.context = context;
        }

        public IEnumerable<Flow> Get()
        {
            return context.Flows;
        }

        /// <summary>
        /// Tìm ra luồng bởi id truyền vào
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Flow GetById(object id)
        {
            return context.Flows.Find(int.Parse(id.ToString()));
        }

        public IEnumerable<Flow> FindByName(object s)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Thêm mới một luồng
        /// </summary>
        /// <param name="T"></param>
        public void Insert(Flow T)
        {
            if (null != T)
            {
                context.Flows.Add(T);
                Save();
            }
        }

        /// <summary>
        /// xóa luồng
        /// </summary>
        /// <param name="id"></param>
        public void Delete(object id)
        {
            var item = GetById(id);
            if (item != null)
            {
                Delete(item);
            }
        }

        public void Delete(Flow T)
        {
            if (T != null)
            {
                context.Flows.Attach(T);
                context.Flows.Remove(T);
                Save();
            }
        }

        public void Update(Flow T)
        {
            if (null != T)
            {
                //context.Flows.Attach(T);
                context.Entry(T).State = EntityState.Modified;
                Save();
            }
        }

        public void Save()
        {
            context.SaveChanges();
        }

        /// <summary>
        /// Lấy toàn bộ dữ liệu có phân trang
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public PagedList<Flow> GetWithPaging(int pageIndex, int pageSize)
        {
            return context.Flows.OrderByDescending(o => o.UpdatedAt).Paginate(pageIndex, pageSize);
        }

        /// <summary>
        /// Lấy toàn bộ luồng với doctype truyền vào
        /// </summary>
        /// <param name="doctypeId"></param>
        /// <param name="isActive"></param>
        /// <returns></returns>
        public IEnumerable<Flow> GetByDocType(int doctypeId, bool? isActive = true)
        {
            if (isActive != null)
            {
                return context.Flows.Where(o => o.DocTypeId != null && o.DocTypeId == doctypeId && o.IsActive == isActive).OrderByDescending(o => o.UpdatedAt);
            }
            else
            {
                return context.Flows.Where(o => o.DocTypeId != null && o.DocTypeId == doctypeId).OrderByDescending(o => o.UpdatedAt);
            }
        }

        /// <summary>
        /// Lấy toàn bộ luồng với doctype và các loại dùng chung
        /// </summary>
        /// <param name="doctypeId"></param>
        /// <param name="isActive"></param>
        /// <returns></returns>
        public IEnumerable<Flow> GetByDocTypeAndCommon(int doctypeId, bool? isActive = true)
        {
            if (isActive != null)
            {
                return context.Flows.Where(o => (o.IsCommon == true || o.DocTypeId == doctypeId) && o.IsActive == isActive).OrderBy(o => o.IsCommon).ThenBy(o => o.UpdatedAt);
            }
            else
            {
                return context.Flows.Where(o => o.IsCommon == true || o.DocTypeId == doctypeId).OrderBy(o => o.IsCommon).ThenBy(o => o.UpdatedAt);
            }
        }

        /// <summary>
        /// Lấy toàn bộ luồng dùng chung hoặc không dùng chung
        /// </summary>
        /// <param name="isCommon"></param>
        /// <param name="isActive"></param>
        /// <returns></returns>
        public IEnumerable<Flow> GetByCommon(bool isCommon, bool? isActive = true)
        {
            if (isActive != null)
            {
                return context.Flows.Where(o => o.IsCommon == isCommon && o.IsActive == isActive).OrderBy(o => o.UpdatedAt);
            }
            else
            {
                return context.Flows.Where(o => o.IsCommon == isCommon).OrderBy(o => o.UpdatedAt);
            }
        }

        /// <summary>
        /// Tìm kiếm theo khóa, tìm với tên luồng
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public IEnumerable<Flow> SearchFlow(string key)
        {
            return context.Flows.Where(o => o.Name.Contains(key)).OrderByDescending(o => o.UpdatedAt);
        }

        /// <summary>
        /// Lấy toàn bộ luồng, active true hoặc false
        /// </summary>
        /// <param name="isActive"></param>
        /// <returns></returns>
        public IEnumerable<Flow> GetByActive(bool? isActive = true)
        {
            if (isActive != null)
            {
                return context.Flows.Where(o => o.IsActive == isActive).OrderBy(o => o.UpdatedAt);
            }
            else
            {
                return context.Flows.OrderBy(o => o.UpdatedAt);
            }
        }

        /// <summary>
        /// Chỉ có một luồng được chọn ưu tiên chọn mặc định từ các thông tin truyền vào
        /// </summary>
        /// <param name="docTypeId"></param>
        /// <param name="departmentId"></param>
        public void UniqueDefault(int? docTypeId, int? departmentId)
        {
            List<Flow> flows = null;
            if (docTypeId != null && departmentId != null)
            {
                flows = context.Flows.Where(o => o.DocTypeId == docTypeId && o.DepartmentId == departmentId && o.IsDefault == true).ToList();
            }
            else if (docTypeId == null && departmentId != null)
            {
                flows = context.Flows.Where(o => o.IsCommon == true && o.DepartmentId == departmentId && o.IsDefault == true).ToList();
            }
            else if (docTypeId != null)
            {
                flows = context.Flows.Where(o => o.DocTypeId == docTypeId && o.IsDefault == true).ToList();
            }

            if (flows != null && flows.Any())
            {
                flows.ForEach(t =>
                        {
                            t.IsDefault = false;
                            context.Entry(t).State = EntityState.Modified;
                        });
                Save();
            }
        }
    }
}
